package com.huanlis.cloud.controller;

import com.huanlis.cloud.config.OauthSecurityConfiguration;
import com.huanlis.cloud.config.OauthServerConfiguration;
import com.huanlis.cloud.utils.R;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.UUID;

/**
 * 
 *
 * @author lihuan
 * @since 2023/10/26 15:37:02
 */
@RestController
@RequestMapping("/oauth")
public class LoginController {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * Spring Security登录接口的实现，自定义的登录配置在 {@link OauthSecurityConfiguration#configure(AuthenticationManagerBuilder)}的<code>.antMatchers("/oauth/user/login").anonymous()</code>中有配置
     *
     * @author lihuan
     * @since 2023/10/27 9:33
     */
    @PostMapping("/user/login")
    public R login(@RequestParam String username, @RequestParam String password) {

        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);
        if (authenticate == null) {
            return R.fail();
        }
        String string = UUID.randomUUID().toString();
        redisTemplate.opsForValue().set("oauth2:sso:" + string, authenticate.getName());
        return R.success().data(string);
    }


    /**
     * Oauth2认证中心中，授权码模式下授权code返回接口。配置可参考{@link OauthServerConfiguration#configure(ClientDetailsServiceConfigurer)}
     * 中<code>.redirectUris("http://localhost:8001/api/ouath/token", "http://www.baidu.com")</code>配置
     *
     * @param code Oauth重定向带出的code
     * @author lihuan
     * @since 2023/10/27 10:01
     */
    @RequestMapping(value = "/code", params = {"code"})
    public R code(@RequestParam String code) {
        if (code == null || code.isEmpty()) {
            return R.fail();
        }
        return R.success(code);
    }


    /**
     * Oauth2认证中心中，隐藏模式下授权code返回接口。配置可参考{@link OauthServerConfiguration#configure(ClientDetailsServiceConfigurer)}
     * 中<code>.redirectUris("http://localhost:8001/api/ouath/token", "http://www.baidu.com")</code>配置。该接口是Oauth认证服务器生成
     * AccessToken后的回调接口。该接口将access_token获取到后通过自定义封装返回给前端。Oauth的回调请求如下<code>
     * http://localhost:8001/api/oauth/code#access_token=2da10311-c937-4f71-8e3a-19b59c014d6f&token_type=bearer&expires_in=42842</code>
     * @param token Oauth重定向带出的token
     * @param tokenType token的类型
     * @param expiresIn 剩余有效时间
     * @author lihuan
     * @since 2023/10/27 10:01
     */
//    @RequestMapping(value = "/code", params = {"access_token", "token_type", "expires_in"})
    @RequestMapping(value = "/code")
    public R token(@RequestParam("access_token") String token,
                   @RequestParam("token_type") String tokenType,
                   @RequestParam("expires_in") Integer expiresIn) {
        if (token == null || token.isEmpty()) {
            return R.fail();
        }
        HashMap<String, Object> result = new HashMap<>();
        result.put("accessToken", token);
        result.put("tokenType", tokenType);
        result.put("expiresIn", expiresIn);
        return R.success(result);
    }

}
